//
//  MessageSender.swift
//  SecretChat
//
//  Created by TimTiger on 16/6/23.
//  Copyright © 2016年 TimTiger. All rights reserved.
//

import UIKit
import MudFramework

private let PushDevloperAddress = "gateway.sandbox.push.apple.com"
private let PushProductionAddress = "gateway.push.apple.com"

private let shareInstance = PushSender()

public  class PushSender: NSObject {
    /// 推送Socket 客户端
    private var client: SCSockClient!
    // 要推送的信息体
    public var payload: Payload!
    /// 推送专用线程队列
    private lazy var pushQueue: dispatch_queue_t =  { return dispatch_queue_create("PushSenderQueue", DISPATCH_QUEUE_SERIAL) }()

    public class func shareSender()->PushSender {
        return shareInstance
    }
    
    override public init() {
        self.client = SCSockClient(addr: PushDevloperAddress, port: 2195)
        self.payload = Payload()
    }
    
    /**
     将消息推送出去
     */
    public func push() {
        dispatch_async(self.pushQueue) {
            for token in self.payload.deviceTokens {
                let data = self.prepareDataWithToken(token)
                if data != nil {
                    self.client.writeData(data!)
                } else {
                    //TODO
                }
            }
        }
    }

    public func asyncConnect(success: ()->Void,failed: (NSError)->Void) {
        if self.client.isConnected() == true {
                success()
        }
        dispatch_async(self.pushQueue) {
            do {
                try self.client.connectionServer()
                dispatch_async(dispatch_get_main_queue(), {
                    success()
                })
            } catch let error as NSError {
                dispatch_async(dispatch_get_main_queue(), {
                    failed(error)
                })
            }
        }
    }
}

extension PushSender {
    
    //MARK: - Data
    private func prepareDataWithToken(token: String)->NSData? {
        
       let optionalTokenData = String.dataFromHexString(token)
        if optionalTokenData == nil {
            return nil
        }
        let optionalPayloadData = self.payload.data()
        if optionalPayloadData == nil {
            return nil
        }
        let tokenData = optionalTokenData!
        let payloadData = optionalPayloadData!
        
        let bufferSize = sizeof(UInt8)+sizeof(UInt32)*2+sizeof(UInt16)+32+sizeof(UInt16)+256
        let buffer: UnsafeMutablePointer <Void> = malloc(bufferSize)
        var p: UnsafeMutablePointer <Void> = buffer
        var command: UInt8 = 0
        memcpy(p, &command, sizeof(UInt8))
        p += sizeof(UInt8)
        
        var tokenLength = Darwin._OSSwapInt16(UInt16(tokenData.length))
        memcpy(p, &tokenLength, sizeof(UInt16))
        p += sizeof(UInt16);
        
        memcpy(p, tokenData.bytes, tokenData.length);
        p += tokenData.length
        
        var payloadLength = Darwin._OSSwapInt16(UInt16(payloadData.length))
        memcpy(p, &payloadLength, sizeof(UInt16));
        p += sizeof(UInt16)
        
        memcpy(p, payloadData.bytes, payloadData.length);
        p += payloadData.length;
        
        let resultData = NSData(bytes: buffer, length: p-buffer)
        return resultData
    }
}

